package com.coms514.scheduleme;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.mail.AuthenticationFailedException;
import javax.mail.MessagingException;

import org.json.JSONException;
import org.json.JSONObject;

import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.calendar.CalendarScopes;
import com.google.api.services.calendar.model.EventDateTime;

import android.accounts.AccountManager;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.ArrayAdapter;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

public class TodayEventActivity extends Activity {
	static final String TAG = "TodayEventActivity";
	
	// Needed to be set
	static final String mailUser = "scheduleme8@gmail.com";
	static final String mailPass = "tmzpwnfal";
	static final String mailFrom = "scheduleme8@gmail.com"; 
	
	/****/
	// for google play service
	private static final Level LOGGING_LEVEL = Level.OFF;
	private static final String PREF_ACCOUNT_NAME = "accountName";

	static final int REQUEST_GOOGLE_PLAY_SERVICES = 0;
	static final int REQUEST_AUTHORIZATION = 1;
	static final int REQUEST_ACCOUNT_PICKER = 2;

	final HttpTransport transport = AndroidHttp.newCompatibleTransport();
	final JsonFactory jsonFactory = GsonFactory.getDefaultInstance();

	GoogleAccountCredential credential;
	com.google.api.services.calendar.Calendar client;
	/****/
	
	SharedPreferences preferences;
    boolean feedback = false;
	
	TodayEventModel model = new TodayEventModel();
	ArrayList<TodayEventInfo> todayEventInfoList;
	ArrayAdapter<TodayEventInfo> adapter;
	
	// com.google.api.services.calendar.Calendar client;
	int numAsyncTasks;
	private	ScheduleMe myState;
	
	private ListView listView;
	
	ScheduleMeDatabase database;
	boolean dbIsOpen;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// view and menu
		setContentView(R.layout.todayeventlist);
		listView = (ListView)findViewById(R.id.list);

		/****/
		myState = ((ScheduleMe)getApplicationContext());
		//credential = myState.getCredential();
		client = myState.getClient();

		if (client == null) {
			// enable logging
			Logger.getLogger("com.google.api.client").setLevel(LOGGING_LEVEL);
			
			// Google Accounts
			credential = GoogleAccountCredential.usingOAuth2(this, Collections.singleton(CalendarScopes.CALENDAR));
			
			// SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
			SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
			credential.setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));
			
			// Calendar client
			client = new com.google.api.services.calendar.Calendar.Builder(
					transport, jsonFactory, credential).setApplicationName("Google-CalendarAndroidSample/1.0")
					.build();
			
			//myState.setCredential(credential);
			myState.setClient(client);
		}
		/****/
		AsyncLoadTodayEvents.run(this);
		
        preferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
        feedback = preferences.getBoolean("feedback", false);
        
		// open database
		if (database != null) {
			database.close();
			database = null;
		}
		
		database = ScheduleMeDatabase.getInstance(this);
		dbIsOpen = database.open();
	}
	
	void refreshView() {
		todayEventInfoList = model.toArrayList();
		adapter = new MyAdapter(this, R.layout.todayeventlistitem, todayEventInfoList);
		listView.setAdapter(adapter);

		listView.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				TodayEventInfo tei = (TodayEventInfo) parent.getItemAtPosition(position);
				Toast.makeText(getApplicationContext(), "Clicked on : " + tei.getSummary(),
						Toast.LENGTH_LONG).show();
			}
		});
	}

	@SuppressLint("DefaultLocale")
	public void onSend(View view) {
		// check FEEDBACK_TYPE
		// and send a email to caregivers

		String caregiverEmails = getCaregiverEmails();
		if (!feedback) {
			Toast.makeText(getApplicationContext(), "Feedback switch is OFF.\n"
					+ "Please, Turn On your Feedback at Set-Feedback!", Toast.LENGTH_LONG)
			.show();
		} else if (caregiverEmails == null || caregiverEmails == "") {
			Toast.makeText(getApplicationContext(), "There is no Emails.\n"
					+ "Please, Add some Caregivers at Set-Caregiver!", Toast.LENGTH_LONG)
			.show();
		} else {
			String mailTitle = "ScheduleMe Feedback Report (" + new Date() + ")";
			String mailBody = "Have you finished your schedule today?\n";
			for (int i = 0; i < todayEventInfoList.size(); i++) {
				TodayEventInfo tei = todayEventInfoList.get(i);
				
				String startTimeStr = dateTime2TimeString(tei.getStart());
				String endTimeStr = dateTime2TimeString(tei.getEnd());
				
				String buf = String.format(Locale.US, "%d. (%s - %s) %s%s --> %s\n",
						(i + 1),
						startTimeStr, endTimeStr,
						tei.getSummary(),
						(tei.getLocation() != null ? " (" + tei.getLocation() + ")" : ""),
						(tei.getSelected() ? "Yes." : "No."));
				mailBody = mailBody + buf;
			}
			
			/* send a mail using default android mail client */
//			Intent email = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", caregiverEmails, null));
//			email.putExtra(Intent.EXTRA_SUBJECT, mailTitle);
//			email.putExtra(Intent.EXTRA_TEXT, mailBody);
//			startActivity(Intent.createChooser(email, "Send email..."));
			
			String[] toArr = TextUtils.split(caregiverEmails, ";");
			new SendEmailAsyncTask(toArr, mailFrom, mailTitle, mailBody).execute();

			finish();
		}
	}

	public void onCancel(View view) {
		finish();
	}
		
    @Override
    public void onDestroy(){
        super.onDestroy();
        database.close();
    }

	public class MyAdapter extends ArrayAdapter<TodayEventInfo> {
		
		public MyAdapter(Context context, int textViewResourceId, ArrayList<TodayEventInfo> object) {
			super(context, textViewResourceId, todayEventInfoList);
		}

		private class ViewHolder {
			TextView numTextView;
			TextView startEndTextView;
			TextView titleTextView;
			CheckBox checkBox;
		}
		
		public View getView(int position, View convertView, ViewGroup parent) {
			
			ViewHolder holder = null;

			Log.v(TAG, String.valueOf(position));

			if (convertView == null) {
				LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);

				convertView = vi.inflate(R.layout.todayeventlistitem, null);

				holder = new ViewHolder();
				holder.numTextView = (TextView) convertView.findViewById(R.id.num_entry);
				holder.startEndTextView = (TextView) convertView.findViewById(R.id.startend_entry);
				holder.titleTextView = (TextView) convertView.findViewById(R.id.summary_entry);
				holder.checkBox = (CheckBox) convertView.findViewById(R.id.selected_checkbox);

				convertView.setTag(holder);

				holder.checkBox.setOnClickListener(new View.OnClickListener() {
					public void onClick(View v) {
						CheckBox cb = (CheckBox) v;
						TodayEventInfo tei = (TodayEventInfo) cb.getTag();

//						Toast.makeText(getApplicationContext(), "Checkbox: " + cb.getText()
//								+ " -> " + cb.isChecked(), Toast.LENGTH_LONG)
//								.show();

						tei.setSelected(cb.isChecked());
					}
				});

			} else {
				holder = (ViewHolder) convertView.getTag();
			}

			TodayEventInfo tei = todayEventInfoList.get(position);

			println("tei.getStart():" + (tei.getStart() != null ? tei.getStart().toString() : ""));
			println("tei.getEnd(): " + (tei.getEnd() != null ? tei.getEnd().toString() : ""));
			println("tei.getLocation(): " + (tei.getLocation() != null ? tei.getLocation().toString() : ""));
			
			String startTime = dateTime2TimeString(tei.getStart());
			String endTime = dateTime2TimeString(tei.getEnd());
			
			holder.numTextView.setText((position + 1) + ". ");
			if (startTime != null) {
				holder.startEndTextView.setText(startTime + "\n-" + endTime);	
			} else {
				holder.startEndTextView.setText("");
			}
			
			if (tei.getLocation() != null) {
				holder.titleTextView.setText(tei.getSummary() + "(" + tei.getLocation() + ")");
			} else {
				holder.titleTextView.setText(tei.getSummary());
			}
			
			// holder.checkBox.setText(tei.getSummary());
			holder.checkBox.setChecked(tei.getSelected());
			holder.checkBox.setTag(tei);

			return convertView;
		}
	}
	
	private static String dateTime2TimeString(EventDateTime eventDateTime) {
		
		if (eventDateTime == null) {
			return null;
		}
		
		String dateStr = null;
		try {
			JSONObject obj = new JSONObject(eventDateTime.toString());
			dateStr = obj.getString("dateTime");
		} catch (JSONException je) {
			Log.e(TAG, "Error", je);
		}
		
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
		DateFormat tf = new SimpleDateFormat("HH:mma", Locale.US);

		Date date = null;
		try {
			if (dateStr != null) {
				date = df.parse(dateStr);
			}
		} catch (ParseException pe) {
			Log.e(TAG, "Error", pe);
		}
		String timeStr = (date != null ? tf.format(date) : null);
		return timeStr;
	}
	
	private String getCaregiverEmails() {
  		String selectCaregiverEmail = "select email from caregiver";
  		Cursor cursor = database.rawQuery(selectCaregiverEmail);
  		
		ArrayList<String> emailList = new ArrayList<String>();
		for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
			emailList.add(cursor.getString(cursor.getColumnIndex("email")));
		}
		cursor.close();
		
		return(TextUtils.join(";", emailList));
	}
	
	/****/
  
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		
		switch (requestCode) {
			case REQUEST_GOOGLE_PLAY_SERVICES:
				if (resultCode == Activity.RESULT_OK) {
					haveGooglePlayServices();
				} else {
					checkGooglePlayServicesAvailable();
				}
				break;
			case REQUEST_AUTHORIZATION:
				if (resultCode == Activity.RESULT_OK) {
					AsyncLoadTodayEvents.run(this);
				} else {
					chooseAccount();
				}
				break;
			case REQUEST_ACCOUNT_PICKER:
				if (resultCode == Activity.RESULT_OK && data != null && data.getExtras() != null) {
					String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);
					if (accountName != null) {
						credential.setSelectedAccountName(accountName);
						// SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
						SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
						SharedPreferences.Editor editor = settings.edit();
						editor.putString(PREF_ACCOUNT_NAME, accountName);
						editor.commit();
						
						AsyncLoadTodayEvents.run(this);
					}
				}
				break;
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.main_menu, menu);
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
			case R.id.menu_refresh:
				// AsyncLoadCalendars.run(this);
				AsyncLoadTodayEvents.run(this);
				break;
			case R.id.menu_accounts:
				chooseAccount();
				return true;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	protected void onResume() {
		super.onResume();
		//if (checkGooglePlayServicesAvailable()) {
		//	haveGooglePlayServices();
		//}
	}

	/** Check that Google Play services APK is installed and up to date. */
	private boolean checkGooglePlayServicesAvailable() {
		final int connectionStatusCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
		
		if (GooglePlayServicesUtil.isUserRecoverableError(connectionStatusCode)) {
			showGooglePlayServicesAvailabilityErrorDialog(connectionStatusCode);
			return false;
		}
		return true;
	}

	// for google play service
	void showGooglePlayServicesAvailabilityErrorDialog(final int connectionStatusCode) {
		runOnUiThread(new Runnable() {
			public void run() {
				Dialog dialog = GooglePlayServicesUtil.getErrorDialog(
						connectionStatusCode, TodayEventActivity.this, REQUEST_GOOGLE_PLAY_SERVICES);
				dialog.show();
			}
		});
	}

	private void haveGooglePlayServices() {
		// check if there is already an account selected
		if (credential.getSelectedAccountName() == null) {
			// ask user to choose account
			chooseAccount();
		} else {
			// load today events
			AsyncLoadTodayEvents.run(this);
		}
	}

  	private void chooseAccount() {
  		startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
  	}
  	
  	/****/
  	
	/* for logging */
	private void println(String msg) {
		Log.d(TAG, msg);
	}
	
	
	/****/
    //new SendEmailAsyncTask().execute();
	
	class SendEmailAsyncTask extends AsyncTask <Void, Void, Boolean> {
		Mail m = new Mail(mailUser, mailPass);

		public SendEmailAsyncTask(String[] toArr, String from, String subject, String body) {
			if (BuildConfig.DEBUG)
				Log.v(SendEmailAsyncTask.class.getName(), "SendEmailAsyncTask()");
			
			m.setTo(toArr);
			m.setFrom(from);
			m.setSubject(subject);
			m.setBody(body);
		}

		@Override
		protected Boolean doInBackground(Void... params) {
			if (BuildConfig.DEBUG)
				Log.v(SendEmailAsyncTask.class.getName(), "doInBackground()");
			
			try {
				m.send();
				return true;
			} catch (AuthenticationFailedException e) {
				Log.e(SendEmailAsyncTask.class.getName(), "Bad account details");
				e.printStackTrace();
				return false;
			} catch (MessagingException e) {
				Log.e(SendEmailAsyncTask.class.getName(), m.getTo() + "failed");
				e.printStackTrace();
				return false;
			} catch (Exception e) {
				e.printStackTrace();
				return false;
			}
		}
	}
	/****/
}
